/*
* Copyright (c) 2011 adVolition
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* Except as contained in this notice, the name(s) of the above
* copyright holders shall not be used in advertising or otherwise to
* promote the sale, use or other dealings in this Software without prior
* written authorization.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
 */

package NeuralNetwork;
import java.lang.Math.*;
import com.thoughtworks.xstream.annotations.*;

/**
 * This class is used to manage parameters in the neural simulator.  It
 * adds important functionality to neural parameters by supporting error-prone
 * copying of the parameters in subsequent generations.
 */
public class Trait {

    @XStreamAlias("prob") @XStreamAsAttribute protected Double _probability;
    @XStreamAlias("wobble") @XStreamAsAttribute protected Double _wobble;
    
    protected transient Double _maximumProbability;
    protected transient Double _minimumProbability;

    public Trait(Double value, Double minimumProbability, Double maximumProbability, Double wobble) {
            _probability = value;
            _minimumProbability = minimumProbability;
            _maximumProbability = maximumProbability;
            _wobble = wobble;
            readResolve();
    }

    public Object readResolve() {
        if (_probability == null) _probability = 0.1;
        if (_wobble == null) _wobble = 0.9;
        if (_minimumProbability == null) _minimumProbability = 0.0;
        if (_maximumProbability == null) _maximumProbability = 0.2;
        return this;
    }


    public Double getProbability() {
        return _probability;
    }

 

    /**
     * This is an error-prone method for cloning the object.  It is used to generate mutant robot offspring.
     * @return
     */
    public Trait getClone() {
        Trait child = new Trait(cloneProbability(), _minimumProbability, _maximumProbability, cloneWobble());
        return child;
    }

    /**
     * This function allows the parameter value to change whenever it is cloned.
     * @return
     */
    private Double cloneProbability() {
        if (Math.random() > _wobble) {
            return Math.random() * (_maximumProbability - _minimumProbability) - _minimumProbability;
        }
        return _probability;
    }

    private Double cloneWobble() {
        if (Math.random() > 0.9) {
            return Math.random();
        }
        return _wobble;
    }

}
